﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Objects;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Web;
using System.Web.Mvc;
using MusicHouse.Models;
using System.Transactions;
using MusicHouse.Models.Views;
using MusicHouse.Util;
using Microsoft.Web.Helpers;

namespace MusicHouse.Controllers
{
    public class AccountController : Controller
    {
        public struct Roteamento
        {
            public string Action { get; set; }
            public string Controler { get; set; }
        }
        private readonly casamusicaEntities1 _db = new casamusicaEntities1();
        
        #region Index

        public ActionResult Index()
        {
            ViewBag.DisplaySucesso = Session["ExibirMensagemSucesso"] == null ? "display:none;" : "display:block";
            Session.Remove("ExibirMensagemSucesso");
            Usuario usu = AccountManager.RetornarUsuarioCookie();
            return View(usu ?? new Usuario());
        }

        
        [HttpPost]
        public ActionResult Index(Usuario usu)
        {

            if (ModelState.IsValid)
            {
                string senhaCrypt = Criptografia.Criptografar(usu.Password, Criptografia.CryptoKey);
                int qtde = _db.usuario.Count(u => u.Ativo && u.LoginEmail.Equals(usu.LoginEmail) && u.Password.Equals(senhaCrypt));
                if (qtde == 0)
                {
                    ModelState.AddModelError("LoginEmail", "E-mail ou Senha inválidos.");
                }

                if (ModelState.IsValid)
                {
                    Session.Add("usuario", _db.usuario.FirstOrDefault(u => u.Ativo && u.LoginEmail.Equals(usu.LoginEmail) && u.Password.Equals(senhaCrypt)));

                    /*HttpCookie cook = new HttpCookie("usuario") { Value = usu.LoginEmail, Expires = DateTime.Now.AddMonths(30) };
                    Response.AppendCookie(cook);
                    */
                    //return Redirect("/Home/Index");

                    Roteamento rot = GetRoteamentoQueryString();

                    //return RedirectToAction("Index", "Home");
                    return RedirectToAction(rot.Action, rot.Controler);
                }
            }
            return View(usu);
        }

        private Roteamento GetRoteamentoQueryString(string action="Index", string controler="Home")
        {
            string returnUrl = Request.QueryString["returnUrl"];
            if (!string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = Criptografia.Descriptografar(returnUrl, Criptografia.CryptoKey);
                string[] parametros = returnUrl.Split(',');
                string actionName = parametros[0];
                string controlerName = parametros[1];
                return new Roteamento {Action = actionName, Controler = controlerName};
            }
            return new Roteamento {Action = action, Controler = controler};
        }

        #endregion
        
        #region Register

        public ActionResult Register()
        {
            Response.Cookies.Remove("usuario");
            Session.Remove("usuario");
            
            ViewBag.DisplaySucesso = false;
            ViewBag.IdUf = new SelectList(_db.uf, "IdUf", "Nome");
            return View();
        }

        [HttpPost]
        public ActionResult Register(Usuario usu)
        {

            Response.Cookies.Remove("usuario");
            Session.Remove("usuario");
            ViewBag.DisplaySucesso = false;

            #region Validacoes

#if !DEBUG
            if (!ReCaptcha.Validate(ConfigurationManager.AppSettings["ReCaptcha.PrivateKey"]))
            {
                ModelState.AddModelError("", "Código de segurança (ReCaptcha) Não confere.");
            }
#endif


            if (string.IsNullOrWhiteSpace(usu.PasswordCompare))
            {
                ModelState.AddModelError("PasswordCompare", "Confirmação da Senha é Obrigatória.");
            }
            if (string.IsNullOrWhiteSpace(usu.Nome))
            {
                ModelState.AddModelError("Nome", "Nome é Obrigatório.");
            }

            if (usu.Password != usu.PasswordCompare)
            {
                ModelState.AddModelError("PasswordCompare", "Senha não Confere com a Cofirmação.");
            }

            #endregion
            
            if (ModelState.IsValid)
            {
                using (var tScope = new TransactionScope(TransactionScopeOption.Required))
                {
                    #region dados do usuario

                    usu.Ativo = false;
                    usu.Password = Criptografia.Criptografar(usu.Password, Criptografia.CryptoKey);
                    usu.Nivel = Usuario.NiveisUsuario.NaoDefinido.GetHashCode();
                    usu.CodigoConfirmacao = Guid.NewGuid().ToString().ToUpper().Replace("-", string.Empty);

                    #endregion

                    _db.usuario.AddObject(usu);
                    _db.SaveChanges();
                    string currentControllerName = (string)RouteData.Values["controller"];
                    //string currentActionName = (string) RouteData.Values["action"];

                    #region Enviar Email

                    string remetenteEmail = ConfigurationManager.AppSettings["RemetenteEmail"]; //O e-mail do remetente
                    string passwordEmail = ConfigurationManager.AppSettings["PasswordEmail"];
                    SmtpClient client = new SmtpClient();
                    client.Credentials = new NetworkCredential(remetenteEmail, passwordEmail);
                    client.EnableSsl = false;  //Adicionando as credenciais do seu e-mail e senha:

                    var mail = new MailMessage
                    {
                        From = new MailAddress(remetenteEmail, "Casa Música", Encoding.UTF8),
                        Subject = string.Format("Confirmação de Registro de {0}", usu.Nome),
                        SubjectEncoding = Encoding.UTF8,
                        Body = string.Format(@"
Sr(a). {0}, <br /><br />
Obrigado por se Registrar no <a href='www.casamusica.com.br'>Casa Música</a><br /><br />
para confirmar seu cadastro, acesse a opção confirmar cadastro e forneça o codigo: {1}<br /><br />
ou utilize a url abaixo: http://www.casamusica.com.br/{2}/ConfirmarCadastro?qString={1} <br /><br />

Cordialmente,<br /><br />
Casa Música
", usu.Nome, usu.CodigoConfirmacao, currentControllerName),
                        BodyEncoding = Encoding.UTF8,
                        IsBodyHtml = true,
                        Priority = MailPriority.Normal
                    };

                    mail.To.Add(usu.LoginEmail);
                    //mail.Bcc.Add(remetenteEmail);

                    try
                    {
                        client.Send(mail);
                    }
                    catch
                    {
                        //  so reporta erro se nao for debug para funcionar no ambiente de desenvolvimento
#if !DEBUG
                        throw;
#endif
                        Console.WriteLine(mail.Body);
                    }

                    #endregion

                    tScope.Complete();

                }

                //HttpCookie cook = new HttpCookie("usuario") { Value = usu.LoginEmail, Expires = DateTime.Now.AddMonths(30) };
                //Request.Cookies.Add(cook);
                ViewBag.DisplaySucesso = true;
                ViewBag.IdUf = new SelectList(_db.uf, "IdUf", "Nome", usu.IdUf);
                return View(usu);
            }
            usu.Password = string.Empty;
            usu.PasswordCompare = string.Empty;
            ViewBag.IdUf = new SelectList(_db.uf, "IdUf", "Nome", usu.IdUf);

            return View();
        }
        #endregion

        #region Confirmar Cadastro

        public ActionResult ConfirmarCadastro(string qString)
        {
            if (!string.IsNullOrWhiteSpace(qString))
            {
                Confirmar(qString);
                ViewBag.MensagemConfirmacao = "Cadastro confirmado com sucesso.";
                return RedirectToAction("ConfirmacaoSuccess");
            }

            return View();
        }

        [HttpPost]
        public ActionResult ConfirmarCadastro(Usuario usu)
        {
            string codConf = usu.CodigoConfirmacao;
            if (string.IsNullOrWhiteSpace(codConf))
            {
                ModelState.AddModelError("CodigoConfirmacao", "Codigo de confirmação é obrigatório.");
            }
            else
            {
                Confirmar(codConf);
                ViewBag.MensagemConfirmacao = "Cadastro confirmado com sucesso.";
                return RedirectToAction("ConfirmacaoSuccess");

            }
            return View(usu);
        }

        public ActionResult ConfirmacaoSuccess()
        {
            return View();
        }

        #endregion

        #region Esqueceu a Senha
        public ActionResult EsqueceuSenha()
        {
            if (Session["usuario"] != null)
            {
                var usu = Session["usuario"] as Usuario;
                var modelo = new Models.Views.EsqueceuSenha {LoginEmail = usu.LoginEmail};
                return View(modelo);
            }
            return View();
        }

        [HttpPost]
        public ActionResult EsqueceuSenha(Models.Views.EsqueceuSenha modelo)
        {
            ViewBag.MensagemConfirmacao = string.Empty;
            if (!string.IsNullOrWhiteSpace(modelo.LoginEmail))
            {
#if !DEBUG
            if (!ReCaptcha.Validate(ConfigurationManager.AppSettings["ReCaptcha.PrivateKey"]))
            {
                ModelState.AddModelError("", "Código de segurança (ReCaptcha) Não confere.");
                return View(modelo);
            }
#endif

                int qtde = _db.usuario.Count(u => u.Ativo && u.LoginEmail.Equals(modelo.LoginEmail));
                if (qtde == 0)
                {
                    ModelState.AddModelError("LoginEmail", string.Format("E-mail não cadastrado."));
                }
                else
                {
                    var usu =_db.usuario.FirstOrDefault(u => u.Ativo && u.LoginEmail.Equals(modelo.LoginEmail));
                    string senhaReset = Guid.NewGuid().ToString().ToUpper().Replace("-", string.Empty).Substring(0, 12);
                    using (var tScope = new TransactionScope(TransactionScopeOption.Required))
                    {
                        var usuPass = _db.usuario.FirstOrDefault(u => u.Ativo && u.LoginEmail.Equals(usu.LoginEmail));
                        usuPass.Password = Criptografia.Criptografar(senhaReset, Criptografia.CryptoKey);
                        _db.ObjectStateManager.ChangeObjectState(usuPass, EntityState.Modified);
                        _db.SaveChanges(SaveOptions.DetectChangesBeforeSave);
                        tScope.Complete();

                        #region Envio de email
                        string remetenteEmail = ConfigurationManager.AppSettings["RemetenteEmail"]; //O e-mail do remetente
                        string passwordEmail = ConfigurationManager.AppSettings["PasswordEmail"];
                        SmtpClient client = new SmtpClient();
                        client.Credentials = new NetworkCredential(remetenteEmail, passwordEmail);
                        client.EnableSsl = false;  //Adicionando as credenciais do seu e-mail e senha:

                        MailMessage mail = new MailMessage
                        {
                            From = new MailAddress(remetenteEmail, "Casa Música", Encoding.UTF8),
                            Subject = string.Format("Nova senha do Casa Música gerada para {0}", usuPass.Nome),
                            SubjectEncoding = Encoding.UTF8,
                            Body = string.Format(@"
Sr(a). {0}, <br /><br />
Foi solicitado uma nova senha no site <a href='www.casamusica.com.br'>Casa Música</a>.<br /><br />
Sua nova senha é: {1}<br /><br />
você poderá trocar a senha no próprio site em: http://www.Casamusica.com.br/Account/TrocarSenha <br /><br />

Cordialmente,<br /><br />
Casa Música
", usuPass.Nome, senhaReset),
                            BodyEncoding = Encoding.UTF8,
                            IsBodyHtml = true,
                            Priority = MailPriority.Normal
                        };

                        mail.To.Add(usuPass.LoginEmail);
                        //mail.Bcc.Add(remetenteEmail);

                        try
                        {
                            client.Send(mail);
                        }
                        catch
                        {
                            //  so reporta erro se nao for debug para funcionar no ambiente de desenvolvimento
#if !DEBUG
                    throw;
#endif
                            Console.WriteLine(mail.Body);
                        }
                        #endregion

                        ViewBag.MensagemConfirmacao = "Senha Gerada com sucesso, por favor verifique seu e-mail.";
                    }
                }
            }
            else
            {
                ModelState.AddModelError("LoginEmail", string.Format("E-mail é Obrigatório."));

            }
            return View(modelo);
        }
        #endregion

        #region TrocaSenha

        public ActionResult TrocaSenha()
        {
            if (Session["usuario"] == null) return RedirectToAction("Index");
            Usuario usu = (Usuario)Session["usuario"];
            ViewBag.LoginEmail = usu.LoginEmail;

            return View();
        }

        [HttpPost]
        public ActionResult TrocaSenha(TrocaSenha model)
        {
            if (Session["usuario"] == null) return RedirectToAction("Index");
            Usuario usuLog = (Usuario)Session["usuario"];
            ViewBag.LoginEmail = usuLog.LoginEmail;
            string senhaCrypt = Criptografia.Criptografar(model.OldPassword, Criptografia.CryptoKey);

            #region Validacoes

            if (_db.usuario.FirstOrDefault(u => u.Ativo && u.LoginEmail == usuLog.LoginEmail).Password != senhaCrypt)
            {
                ModelState.AddModelError("OldPassword", "Senha Atual não confere.");
            }
            else if (model.OldPassword == model.NewPassword)
            {
                ModelState.AddModelError("NewPassword", "Nova Senha é a atual.");
            }
            else if (model.NewPassword != model.ReNewPassword)
            {
                ModelState.AddModelError("NewPassword", "Senha não Confere com a Cofirmação.");
            }
#if !DEBUG
            if (!ReCaptcha.Validate(ConfigurationManager.AppSettings["ReCaptcha.PrivateKey"]))
            {
                ModelState.AddModelError("", "Código de segurança (ReCaptcha) Não confere.");
            }
#endif
            #endregion


            if (ModelState.IsValid)
            {
                using (var tScope = new TransactionScope(TransactionScopeOption.Required))
                {
                    Usuario usu = _db.usuario.FirstOrDefault(u => u.Ativo && u.LoginEmail == usuLog.LoginEmail);
                    senhaCrypt = Criptografia.Criptografar(model.NewPassword, Criptografia.CryptoKey);
                    usu.Password = senhaCrypt;

                    _db.ObjectStateManager.ChangeObjectState(usu, EntityState.Modified);
                    _db.SaveChanges(SaveOptions.DetectChangesBeforeSave);

                    tScope.Complete();
                    ViewBag.MensagemConfirmacao = "Senha alterdo com sucesso.";

                }
            }

            return View();

        }

        #endregion

        #region Logout
        public ActionResult Logout()
        {
            Response.Cookies.Remove("usuario");
            Session.Remove("usuario");

            return RedirectToAction("Index", "Home");
        }
        #endregion

        #region MeuCadastro

        public ActionResult MeuCadastro()
        {
            ViewBag.DisplaySucesso = false;
            Usuario usu = AccountManager.RetornarUsuarioCookie() ?? Session["usuario"] as Usuario;
            string parametro = Criptografia.Criptografar("MeuCadastro,Account", Criptografia.CryptoKey);
            if (usu==null)
            {
                return RedirectToAction("Index", new { returnUrl = parametro });
            }

            ViewBag.IdUf = new SelectList(_db.uf, "IdUf", "Nome", usu.IdUf);
            return View(usu);
        }

        #endregion


        #region Metodos

        #region Confirmar

        private void Confirmar(string codigoConfirmacao)
        {
            int cont = _db.usuario.Where(u => !u.Ativo && u.CodigoConfirmacao == codigoConfirmacao).Count();
            if (cont == 0)
            {
                ModelState.AddModelError("", "Codigo de Confirmação não encontrado.");
                return;
            }
            using (var tScope = new TransactionScope(TransactionScopeOption.Required))
            {
                Usuario usu = _db.usuario.FirstOrDefault(u => !u.Ativo && u.CodigoConfirmacao == codigoConfirmacao);
                usu.Ativo = true;
                usu.CodigoConfirmacao = string.Empty;
                //Servicos.Db.usuario.Attach(usu);
                //Servicos.Db.AcceptAllChanges();
                _db.ObjectStateManager.ChangeObjectState(usu, System.Data.EntityState.Modified);
                _db.SaveChanges(System.Data.Objects.SaveOptions.DetectChangesBeforeSave);

                tScope.Complete();

            }
        }

        #endregion

        #endregion
    }
}
